package cn.zoujiedev.netty.demo;

import cn.zoujiedev.netty.core.decoder.NettyMessageDecoder;
import cn.zoujiedev.netty.core.encoder.NettyMessageEncoder;
import cn.zoujiedev.netty.core.handler.HeartbeatReqHandler;
import cn.zoujiedev.netty.core.handler.LoginAuthReqHandler;
import cn.zoujiedev.netty.core.serialization.HessianDecoder;
import cn.zoujiedev.netty.core.serialization.HessianEncoder;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.ReadTimeoutHandler;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @Classname Client
 * @Description
 * @Date 2022-11-3 17:04
 * @Created by zoujie
 */
public class NettyClient {

  private ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);

  EventLoopGroup group = new NioEventLoopGroup();

  private String host;

  private int port;

  public NettyClient(String host, int port){
    this.host = host;
    this.port = port;
  }

  public void connect() throws Exception {

    try {
      Bootstrap bootstrap = new Bootstrap();
      bootstrap.channel(NioSocketChannel.class)
          .group(group)
          .option(ChannelOption.TCP_NODELAY,true)
          .handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel socketChannel) throws Exception {
              socketChannel.pipeline().addLast("messageDecoder",new NettyMessageDecoder(1024 * 1024,4,4,new HessianDecoder()));
              socketChannel.pipeline().addLast("messageEncoder",new NettyMessageEncoder(new HessianEncoder()));
              socketChannel.pipeline().addLast("readTimeoutHandler",new ReadTimeoutHandler(50));
              socketChannel.pipeline().addLast("loginAuthHandler",new LoginAuthReqHandler());
              socketChannel.pipeline().addLast("heartbeatHandler",new HeartbeatReqHandler());
            }
          });

      ChannelFuture future = bootstrap.connect(host, port).sync();
      future.channel().closeFuture().sync();

    }finally {

      executorService.execute(() -> {
        try {
          TimeUnit.SECONDS.sleep(5);
          try {
            connect();
          } catch (Exception e) {
            e.printStackTrace();
          }
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      });
    }
  }

  public static void main(String[] args) throws Exception {
    String host = "127.0.0.1";
    int port = 8598;
    new NettyClient(host, port).connect();

  }
}
